home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / str.exe / STR.DOC < prev    next >
Text File  |  1993-04-21  |  64KB  |  1,661 lines

  1. Copyright (c) 1993 by Roy S. Woll 
  2.  
  3. Class "str", Version 2.1     3/10/93
  4.  
  5. You may distribute and sell any executable which results from using this code
  6. in your applications.  You may redistribute this source freely as long as you
  7. leave all files in their original form, including the copyright notice as is.
  8. You may NOT include any SOURCE code of this software with any program that is
  9. sold. 
  10.  
  11. I would sincerely welcome any comments/criticism/ideas you might have about
  12. the str or the regular expression class.
  13.  
  14. If you use the product, please register by sending $15.00 to
  15. Roy S. Woll, 1032 Summerplace Dr., San Jose, CA 95122.  You will receive a
  16. typeset manual, the str library on disk, and updates as they are made
  17. available.
  18.  
  19.  
  20.            ------------------------------------------
  21.            |                                        |
  22.            | Roy S. Woll                            |
  23.            | 1032 Summerplace Dr.                   |
  24.            | San Jose, CA 95122                     |
  25.            |                                        |
  26.            | CompuServe : 76207,2541                |
  27.            |                                        |
  28.            | Phone: (408) 778-2000 x4518  (day)     |
  29.            |        (408) 293-5893        (evening) |
  30.            |                                        |
  31.            ------------------------------------------
  32.  
  33.  
  34.  
  35. In addition those of you who register will receive a more powerful
  36. version of the regular expression class that includes context-sensitive
  37. regular expressions.  For instance you will easily be able to search or 
  38. replace a specific portion (flagged by '@') of a regular expression.
  39.  
  40.             
  41.            regX employeeX("Pay to the order of @[A-Za-z\\s]+$");
  42.            str paycheck("Payroll\nPay to the order of Roy S. Woll\n$50,000");
  43.            str employee;
  44.  
  45.            paycheck.search(employeeX,  &employee); 
  46.            paycheck.replace(employeeX,  "a lucky person");
  47.  
  48.        //
  49.        // After executing the above code, employee will contain the
  50.        // name of the person following the text "Pay to the order of ".
  51.        //
  52.        // employee = "Roy S. Woll"
  53.        // paycheck = "Payroll\nPay to the order of lucky person\n$50,000"
  54.        //   
  55.  
  56.  
  57. ------------------------------------------------------------------------------
  58.  
  59.  
  60.           FILES:  THE FOLLOWING FILES ARE INCLUDED.
  61.           -----------------------------------------
  62.           str.doc        Documentation file for str class
  63.  
  64.           str.h          Interface file for str class
  65.           regX.h         Interface file for regular expression class
  66.           regXimp.h      Interface file used only for implementation of regX
  67.           dynstream.h    Interface file for dynstream class
  68.           bcstr.h        Interface file for BCstr class.  BCstr is compatible
  69.                          with the Borland object-based  container classes.  It
  70.                          is derived from str.
  71.  
  72.           str.cpp        Implementation file for str class
  73.           regX.cpp       Implementation file for regular expression class
  74.           dynstream.cpp  Implementation file for dynstream class
  75.           match.cpp      Regular expression compiling and searching routines
  76.           strsearch.cpp  Member functions relating to search/replace
  77.           bcstr.cpp      Implementation file for BCstr class
  78.           strcmp.cpp     Non-ansi string routines used by str class.  Add this
  79.                          to your library if your system does not have these
  80.                          (stricmp, strnicmp, strupr, strlwr).
  81.           grep.cpp       Demo program for "str" class, supporting file
  82.                          searching of regular expression matches.  Supports
  83.                          wildcard file specifications, case sensitivity, line
  84.                          numbers, etc.)
  85.  
  86.           makefile       This program defines how to build str.lib and
  87.                          grep.exe
  88.           readme         Brief overview
  89.  
  90.  
  91.  
  92. 1 GENERAL OVERVIEW AND DESIGN GOALS
  93. -----------------------------------
  94.  
  95. From the beginning this string class was designed to maximize usability and
  96. efficiency.  The following is a breakdown of some of the design objectives.
  97.  
  98. Composition:  One of the most common operations dealing with strings is to
  99. compose a string from other data.   The user would like to have the
  100. flexibility to naturally express how data is inserted into the composed
  101. string.  Class ostream from the iostream library has one of the most
  102. consistent and natural ways of transferring data I have yet seen.   Streams
  103. already provide all the functionality for converting built-in and user-defined
  104. types to a stream of char.  Thus complete interoperability with class
  105. "ostream" from the iostream library was a primary goal.
  106.  
  107. Efficiency through reference counting:  Every time you pass or return an
  108. object by value, a temporary copy is made of the original object.  Temporary
  109. object creation for string objects can be an expensive operation.  To increase
  110. the efficiency for making copies of "str" objects, reference counting should
  111. be used.  By using reference counting, temporary object creation becomes a
  112. very cheap operation.  Only a pointer is copied to create the new string,
  113. instead of allocating a new pointer, copying the character buffer, and then
  114. deallocating the pointer.
  115.  
  116. Efficiency through user-definable memory allocation:  Allocating and
  117. deallocating memory can be an expensive operation so it should be minimized.
  118. This should be handled by allocating a new data buffer only if the old buffer
  119. is too small to store the new data.  The user should be given the flexibility
  120. to define on an instance basis how much memory to allocate initially and when
  121. the string buffer overflows.
  122.  
  123. Search, replacement, and case sensitivity:  Searching and replacement of
  124. literal or regular expressions within a string should be supported. Searching
  125. should use the case sensitivity of the string being compared.  Case
  126. sensitivity should also extend to all the relational operators.
  127.  
  128.  
  129.  
  130. 2 INSTALLATION AND USE:  
  131. -------------------------
  132.  
  133.           2-1 STR.LIB
  134.           -----------
  135.           Type "make" to compile the source and create a library called
  136.           str.lib.  If you wish to place the object files in your own
  137.           library, insert the .obj files into your library.  You may also
  138.           want to place "str.h", and "regX.h" into your default include
  139.           path.  Bcstr.h is provided for those who wish to use the Borland
  140.           object-based container classes to store str's.
  141.  
  142.           If you are using Turbo C++ instead of Borland C++, edit the
  143.           makefile and substitute "TCC" for "BCC".
  144.  
  145.           Unix, Vax-Vms, and some other systems may also need to add
  146.           strcmp.obj to the library.  this module defines non-ansi string
  147.           routines used by the str class.  Add this to your library if your
  148.           system does not have these (stricmp, strnicmp, strupr, strlwr).
  149.           Do not add these to your library, if your system already defines
  150.           these (ie. Borland compilers).
  151.  
  152.             
  153.  
  154.           2-2 GREP
  155.           --------
  156.           Type make grep.exe to create the executable for grep.  Grep is
  157.           included as a demonstration program for the str class.  It
  158.           supports searching of literal and regular expressions within
  159.           files.  Wildcard file specifications, case sensitivity, line
  160.           numbers, etc. are all supported.  The implementation uses only
  161.           around 1 page of ode, which demonstrates how natural coding is
  162.           when using the regular expression capabilities of the string
  163.           class.
  164.  
  165.             
  166.  
  167.           2-3 UPGRADING
  168.           -------------
  169.           If you are upgrading from version 1, then you will need to
  170.           recompile all .cpp files that use the str class.  This must be
  171.           done since str.h has changed.  You also will need to change
  172.           occurrences of pad or strip to use the global versions.  This must
  173.           be done since the member functions pad and strip now modify their
  174.           object.  See section "Whats changed in 2.00".
  175.  
  176.             
  177.  
  178.           2-4 USING
  179.           ---------
  180.           You will need to include <str.h>, "str.h" in order to use class
  181.           str.  If you also wish to use regular expressions include
  182.           <regX.h>, "regX.h".  Header files "dynstream.h" and "regximp.h"
  183.           are strictly for implementation. and as such are separated into
  184.           other header file.  You should never reference them unless you
  185.           wish to modify their implementation, or derive a new class from
  186.           them.
  187.  
  188.             
  189.  
  190. 3 WHATS DIFFERENT ABOUT VERSION 2.1
  191. -----------------------------------
  192.  
  193.           Version 2.1 extends regular expression support to include context
  194.           sensitive regular expressions.  See section on regular expressions
  195.           for more details.
  196.             
  197.  
  198.           3-1 WHATS NEW IN 2.02 and 2.11
  199.           ------------------------------
  200.           Friend operator >> for reading in strings now directly uses the
  201.           string buffer, so as to remove the 256 character limit.
  202.  
  203.           Grep now supports files in other drives and directories.
  204.  
  205.           Optimizations to efficiency in str::_assign which is used
  206.           by many str member functions.
  207.             
  208.           Regular expression character sets can now contain octal characters.
  209.             
  210.           Fix - Member function "remove" now transfers only necessary 
  211.                 characters.  May have caused Windows application error
  212.                 previously.
  213.  
  214.  
  215. 4 WHATS DIFFERENT ABOUT VERSION 2.0
  216. -----------------------------------
  217.  
  218.           4-1 WHATS NEW IN 2.00
  219.           ---------------------
  220.  
  221.           1. Searching and replacing of character strings and regular
  222.              expressions.
  223.  
  224.           2. Case sensitivity now is a property of each instance of str.  All
  225.              searching and comparing for the str instance automatically
  226.              reflects its case sensitivity.  During comparisons between two
  227.              strings, the case sensitivity of the first argument is used.
  228.              Instances of str modify their case sensitivity through member
  229.              functions setCaseSensitive(int).
  230.             
  231.                {
  232.                   str a=("abcd efgh");
  233.                   a.setCaseSensitive(0);     // a is now case insensitive
  234.                   str b=("ABCD EFGH");
  235.                   cout << a.search("efGH");  // "1"   Found
  236.                   cout << b.search("efGH");  // "0"   Not found
  237.             
  238.                   cout << (a==b);         // "1"    Are equal
  239.                   cout << (b==a);         // "0"    Not equal
  240.                } 
  241.  
  242.           3. Miscellaneous optimizations and fixes.
  243.  
  244.  
  245.           4-2 WHATS GONE IN 2.00
  246.           ----------------------
  247.           Member function iindex is not directly supported.  Instead use
  248.           member function setCaseSensitive(int) to tell a string instance if
  249.           its searching and comparing should be case sensitive or not.  The
  250.           default is case sensitive.
  251.  
  252.  
  253.  
  254.           4-3 WHATS CHANGED IN 2.00
  255.           -------------------------
  256.           Member functions pad and strip now modify their object.  Use
  257.           global functions pad and strip to just return a value.   These
  258.           funtions were changed so that there would be a consistency among
  259.           member functions.  If the member function makes sense to modify
  260.           its object, then it will.  I apologize for those of you who will
  261.           have to change your code to reflect this.  But your code will be
  262.           more readable after you make the modifications.  You'll have to
  263.           change occurrences such as the following.
  264.  
  265.                
  266.  
  267.                Old Way                New Way
  268.                ------------------     ------------------
  269.                str a="abc";           str a = "abc";
  270.                str b = a.pad(10);     str b = pad(a, 10);
  271.  
  272.                
  273.  
  274. 5 SEARCHING/REPLACING
  275. ---------------------
  276.  
  277.           Member functions index, search, replace, and replaceAll are
  278.           provided to find and replace user-defined patterns.  There are
  279.           various forms of each, and can be summarized as follows.
  280.  
  281.           ------------------------------------------------------------------
  282.  
  283.             int index( pattern   [,matchLen]   [,start] );
  284.  
  285.             Find the next occurrence of pattern in this string.
  286.             Returns position where match occurs or -1 if not match is found.
  287.  
  288.             pattern:  pattern can be either a (const char *) or a regX.
  289.  
  290.             matchLen: Only allowed if pattern is a regX.  matchLen is the
  291.                       address of a str where the length of the match is saved.
  292.                       Optional Field.
  293.  
  294.             start:    Can be either a (int *) or an (int).  If it is an (int),
  295.                       then its used to determine where the search is to begin.
  296.                       If it is an (int *) then its used to determine where the
  297.                       search is to begin, and its updated to the position 
  298.                       where the match is found.  Optional Field where the 
  299.                       default is to start at the beginning of the string.
  300.  
  301.  
  302.           ------------------------------------------------------------------
  303.  
  304.             int search( pattern   [,matchPtr]   [,start] );
  305.  
  306.             Find the next occurrence of pattern in this string.
  307.             Returns true if match is found.
  308.  
  309.             pattern:  pattern can be either a (const char *) or a regX.
  310.  
  311.             matchPtr: Only allowed if pattern is a regX.  matchPtr is the
  312.                       address of a str where the match is saved.  
  313.                       Optional Field.
  314.  
  315.             start:    Can be either a (int *) or an (int).  If it is an (int),
  316.                       then its used to determine where the search is to begin.
  317.                       If it is an (int *) then its used to determine where the
  318.                       search is to begin, and its updated to the position 
  319.                       where the match is found.  Optional Field where the 
  320.                       default is to start at the beginning of the string.
  321.  
  322.             
  323.           ------------------------------------------------------------------
  324.  
  325.             int replace( pattern, replaceStr  [,start]   [,numReplace])
  326.  
  327.             Replace occurrences of pattern with replaceStr.
  328.             Returns number of actual replacements.
  329.  
  330.             pattern:    pattern can be either a (const char *) or a regX.
  331.  
  332.             replaceStr: pattern is replaced by replaceStr
  333.  
  334.             start:      Can be either a (int *) or an (int).  
  335.                         If it is an (int), then its used to determine where 
  336.                         the search is to begin.  If it is an (int *) then 
  337.                         its used to determine where the search is to begin, 
  338.                         and its updated to the position immediately after the
  339.                         location where the replacement occurred.  
  340.                         Optional Field where default is to start at the 
  341.                         beginning of the string.
  342.  
  343.             numReplace: Maximum number of replacements to perform.
  344.                         Optional Field where default is 1.
  345.  
  346.             
  347.           ------------------------------------------------------------------
  348.  
  349.             int replaceAll( pattern, replaceStr   [,start])
  350.  
  351.             Replace all occurrences of pattern with replaceStr
  352.             Returns number of actual replacements.
  353.  
  354.             pattern:    pattern can be either a (const char *) or a regX.
  355.  
  356.             replaceStr: pattern is replaced by replaceStr
  357.  
  358.             start:      Can be either a (int *) or an (int).  
  359.                         If it is an (int), then its used to determine where 
  360.                         the search is to begin.  If it is an (int *) then 
  361.                         its used to determine where the search is to begin, 
  362.                         and its updated to the position immediately after the
  363.                         location where the replacement occurred.  
  364.                         Optional Field where default is to start at the 
  365.                         beginning of the string.
  366.             
  367.           ------------------------------------------------------------------
  368.  
  369.  
  370. 6 REGULAR EXPRESSIONS
  371. ---------------------
  372.  
  373.           Regular expressions are a powerful form of searching and replacing
  374.           text.  Instead of pattern matching a literal character string,
  375.           they can match a more general pattern expression.  The regular
  376.           expression class obeys the following pattern rules.
  377.  
  378.           6-1 ONE CHARACTER PATTERN RULES:
  379.           --------------------------------
  380.  
  381.           1. All characters except ( " * + ? . [ ] & $ @ \" ) represent
  382.              themselves.  
  383.  
  384.           2. Special characters preceded by a backslash "\",  represent the
  385.              literal character.  However the following characters when
  386.              preceded by a backslash have special meaning.
  387.              
  388.                        \b        backspace
  389.                        \f        formfeed
  390.                        \n        newline
  391.                        \r        carriage return
  392.                        \t        tab
  393.                        \e        escape
  394.                        \s        space
  395.                        \^        control-character
  396.                        \xddd     character code in hex
  397.                        \ddd      character code in octal
  398.                        \         literal character code
  399.              
  400.  
  401.           3. Period represents any character, with the exception of new line.
  402.              Use [^] to cross line boundaries.
  403.  
  404.           4. Brackets, [ and ], enclose a set of characters.  The set of
  405.              character represents any one of its constituents, or any single
  406.              character not in the given sequence if the sequence starts with
  407.              ^.  Within the sequence, - between two characters denotes the
  408.              inclusive range.  For example, [a-z] represents any lower-case
  409.              letter, [^0-9] represents any non-digit character, [aeiou]
  410.              represents any vowel.
  411.             
  412.  
  413.           6-2 MULTI-CHARACTER PATTERN RULES
  414.           ---------------------------------
  415.  
  416.           1. If * follows a one character pattern, it indicates that the
  417.              previous pattern may appear arbitrarily often, or even not at all
  418.              (0 or more occurrences).
  419.  
  420.           2. If + follows one of these pattern parts, it indicates that the
  421.              previous character pattern appears at least once (1 or more
  422.              occurrences)
  423.  
  424.           3. If ? follows one of these pattern parts, it indicates that the
  425.              previous character pattern has zero or one occurrence.
  426.             
  427.  
  428.           6-3 ANCHORS FOR REGULAR EXPRESSION
  429.           ----------------------------------
  430.  
  431.           1. ^ at the beginning of a pattern represents the beginning of an
  432.              input line.      $ at the end of a pattern represents the end of
  433.              an input line.
  434.  
  435.           2. @ flags what part of the regular expression is actually part of
  436.              the match.  For example the regular expression "[0-9]+\.@[0-9]+"
  437.              will match the fractional part of a floating point number. More
  438.              details are described later.
  439.             
  440.  
  441.           6-4 AMBIGUITY RULES FOR SEARCHING AND REPLACING
  442.           -----------------------------------------------
  443.  
  444.           Chooses the pattern that represents the longest possible match.
  445.  
  446.           For instance consider the following example,
  447.  
  448.             
  449.                regX pattern("Numbers .*[0-9]+");
  450.                str a("Numbers 34,67");
  451.                a.search(pattern, &match);   // match = "Numbers 34,67
  452.  
  453.  
  454.           Both "Numbers 34,67" and "Numbers 34" match the pattern, but
  455.           "Numbers 34,67" is chosen since it is longer.
  456.  
  457.             
  458.  
  459.           6-5 CONTEXT SENSITIVE REGULAR EXPRESSIONS
  460.           -----------------------------------------
  461.  
  462.           Quite often one knows the context of what is being looked for, but
  463.           does not have any natural way of expressing this in a regular
  464.           expression format.  Consider the following problem.
  465.  
  466.           Problem:
  467.  
  468.               Write a program that parses a paragraph and removes the comma 
  469.               from all numbers of the form (ddd,ddd,...).  Commas used in 
  470.               any other context should not be affected.
  471.  
  472.           Solution:
  473.  
  474.               void RemoveNumberComma(str * buffer)
  475.               {
  476.                  regX commaInDigitX("[0-9]@,@[0-9]");
  477.                  buffer->replaceAll(commaInDigitX, "");
  478.               };
  479.             
  480.               str a("Hi, this is test number 3, and the year is 1,992.");
  481.               RemoveNumberComma(&a);
  482.             
  483.  
  484.           The above code replaces the number 1,992 with 1992.   The regular
  485.           expression commaInDigitX is context aware.   The user is not
  486.           forced to distinquish for himself if the comma is in a digit or
  487.           not.  Without context aware regular expresions, the above problem
  488.           is more difficult.  The programmer would be required to search for
  489.           a comma, and then check the next and previous characters to see if
  490.           they were a digit before performing the replacement.
  491.  
  492.  
  493.           Here is another example.
  494.  
  495.             
  496.             regX AuthorX("Please register by sending $15 to @[A-Za-z\\s]+$");
  497.             str registration("Please register by sending $15 to Roy S. Woll");
  498.             str author;
  499.             registration.search(AuthorX, &author);   // author = "Roy S. Woll"
  500.  
  501.             
  502.  
  503.           6-6 REGULAR EXPRESSION EXAMPLES:
  504.           --------------------------------
  505.             
  506.             {  
  507.             
  508.                regX number("[0-9]+");
  509.                regX anyWhiteSpace("[\t\\s]+");
  510.                regX leadingWhiteSpace("^[\t\\s]+");
  511.             
  512.             //
  513.             // replacement
  514.             //
  515.                str a("This year is 1992");
  516.                a.replace( number, "1993");      // a = "This year is 1993"
  517.             
  518.                a = "     \tA great string class";
  519.                a.replace( leadingWhiteSpace, "");// a = "A great string class"
  520.             
  521.                a = "A  great    string  \t class";
  522.                a.replaceAll( anyWhiteSpace, " ");// a = "A great string class"
  523.             
  524.             //
  525.             // searching
  526.             //
  527.                str match;
  528.                a = "This year is 1992";
  529.                if (a.search(number))         // "found"
  530.                   cout << "found" << endl;
  531.             
  532.                a.search(number, &match)      // match = "1992"
  533.             
  534.                a = "My wife was born on April 12, 1968.";
  535.                int pos=0;
  536.                a.search(number, &match, &pos);  // match = "12";
  537.                pos+=match.length();
  538.                a.search(number, &match, &pos);  // match = "1968";
  539.             
  540.             }
  541.  
  542.  
  543.           6-7 OPTIMIZATION HINTS FOR REGULAR EXPRESSIONS
  544.           ----------------------------------------------
  545.           Since regular expression compilation (during construction or
  546.           assignment) is a relatively slow operation, you should try to
  547.           minimize them by declaring them as static if at all possible..  In
  548.           this way they will only be compiled once.  
  549.  
  550.             
  551. 7 MEMORY ALLOCATION CONTROL
  552. ---------------------------
  553.  
  554.           To reduce the overhead of continually creating and destroying str
  555.           objects, the str class allows the user to customize how much
  556.           memory to allocate initially and when the string buffer is full.
  557.           The original buffer is used until an operation causes it to grow
  558.           beyond its original size.  The new size is the original size plus
  559.           the increment size.  For example consider the following code
  560.           fragment.
  561.  
  562.              {
  563.                str example2("abcdefg", 10, 15);
  564.                // An instance of str is defined to contain "abcdefg".  
  565.                // Its initial buffer size is 10 characters, and it grows 
  566.                // by 15 bytes when it needs to expand.  
  567.             
  568.                example2 = "123";
  569.                // Assign "123" to example2.  No memory reallocation 
  570.                // is necessary since the new contents still fit in 
  571.                // the original buffer.
  572.             
  573.                example2 = "0123456789012";
  574.                // Assign "0123456789012" to example2.  Memory reallocation is 
  575.                // necessary since the new contents exceed the original size of
  576.                // ten characters.  This assignment causes a new buffer
  577.                // to be created that supports (10+15) bytes.
  578.              }
  579.             
  580.           The Default value for the initial memory allocation size is the
  581.           length of the first value being stored.  The Default value for the
  582.           memory expansion increment is 256 characters. If you'd rather have
  583.           the string truncate rather than expand, use an increment of 0.  If
  584.           you would like to change the default, then edit the str.h file and
  585.           modify the constant str_default_memincr.
  586.  
  587.  
  588.  
  589. 8 INTEROPERABILITY WITH OSTREAM
  590. -------------------------------
  591.  
  592.           Of primary importance in the design of the class was to allow
  593.           complete interoperability with class "ostream" from the iostream
  594.           library.  Class "str" supports all the ostream operations,
  595.           including complete usage of the I/O manipulators.  Streams already
  596.           provide all the functionality for converting built-in and
  597.           user-defined types to a stream of char.  Rather then trying to
  598.           duplicate this, the str class works with the  stream class.
  599.  
  600.           For example, the following module takes 3 integers and returns a
  601.           time specification into a string of the format "hh:mm:ss".
  602.  
  603.              
  604.  
  605.                str getTimeStr(int hour, int minute, int second)
  606.                {
  607.                   str timestr;
  608.                   timestr.stream()  << setfill('0') << setw(2) << hour
  609.                      << ":" << setfill('0') << setw(2) << minute
  610.                      << ":" << setfill('0') << setw(2) << second;
  611.                   return timestr;
  612.                };
  613.             
  614.  
  615.           This method has significant advantages over class "ostrstream".
  616.           Class "ostrstream" has the disadvantages of not being
  617.           interchangeable with "const char *", not having control over
  618.           memory allocation/reallocation, and not supporting string
  619.           operators and member functions.  I also found it significantly
  620.           more cumbersome to use.
  621.  
  622.           Class "str" gives the user full access to ostream's capabilities,
  623.           while maintaining consistency with the str's buffer.
  624.  
  625.             
  626.  
  627. 9 REFERENCE COUNTING
  628. --------------------
  629.  
  630.           To increase the efficiency for making a copy of a "str" object,
  631.           reference counting is used.  You may think you rarely make copies
  632.           of str objects, but that is probably not the case.  Every time you
  633.           pass or return an object by value, a temporary copy is made of the
  634.           original object.  Temporary object creation for string objects can
  635.           be an expensive operation.  
  636.  
  637.           By using reference counting, temporary object creation becomes a
  638.           very cheap operation.  Only a pointer is copied to create the new
  639.           string, instead of allocating a new pointer, copying the character
  640.           buffer, and then deallocating the pointer.
  641.  
  642.             
  643.           For example:
  644.             
  645.                   {
  646.             
  647.             (1)         str a = "just some string   ";
  648.             (2)         str b = a;                     
  649.             
  650.             (3)         str c = a + b;               
  651.             (4)         str c = strip(a);
  652.             
  653.                   }
  654.             
  655.  
  656.  
  657.           Statement (1) creates a str object containing "just some string".
  658.           Statement (2) copies a to b.  With reference counting only a
  659.           pointer is copied.  Without reference counting all the character
  660.           data is transferred.  In statement (3) a temporary str object is
  661.           returned by (a+b) and copied to c.  Using reference counting only
  662.           the pointer for the temporary is copied,  instead of the whole
  663.           character buffer.  Statement (4) is just like statement (3) where
  664.           strip(a) returns a temporary which is copied to c.
  665.  
  666.           However reference counting itself can present some efficiency
  667.           problems.  The popular scheme of having a reference pointer, and a
  668.           data pointer has the disadvantage of slowing down operations for
  669.           singly referenced objects.  This is caused by the need to allocate
  670.           two unique pointers, and the extra level of indirection when
  671.           accessing the character buffer.
  672.  
  673.           The "str" class uses a single pointer that points to block that
  674.           contains both the reference data and the character data.  In this
  675.           way at most one memory allocation is done per operation, making
  676.           the execution times for creating singly referenced objects
  677.           comparable to classes that don't use reference counting. 
  678.  
  679.  
  680. STR REFERENCE
  681. constructor str(void); 
  682.  
  683.             Construct a str where the memory allocation is determined by the
  684.             first assignment to the instance, and then it grows  by
  685.             str_default_memincr.
  686.  
  687.             
  688.  
  689. constructor str(int bufsize, int memincr= str_default_memincr);
  690.  
  691.             Construct a str that allocates a (bufsize) byte buffer during the
  692.             first assignment, and thereafter grows by  (memincr) bytes when
  693.             buffer is full.
  694.  
  695.             
  696.  
  697. constructor str(const char * s, int bufsize=0, memincr=str_default_memincr);
  698. constructor str(const str& s, int bufsize=0, memincr=str_default_memincr);
  699.  
  700.             Construct a str containing (s). It allocates a (bufsize) byte
  701.             buffer during the first  assignment (or the length of (s) if
  702.             larger than bufsize), and thereafter grows by (memincr) bytes when
  703.             the buffer is full.  Use (memincr=0) to prevent the string from
  704.             growing.
  705.  
  706.             
  707.             Constructor examples:
  708.             
  709.             //
  710.             // Memory allocation determined by first assignment 
  711.             // to instance, and then grows by str_default_memincr. 
  712.             //
  713.                str mystr; 
  714.             
  715.             //
  716.             // Defines 10 instances of str. 
  717.             // Memory allocation determined by first assignment 
  718.             // to instance, and then grows by str_default_memincr. 
  719.             //
  720.                str str_array[10];  
  721.             
  722.             // 
  723.             // Define str containing "Some demo text"  100 byte buffer space 
  724.             // allocated, and then grows by 200 bytes when buffer is full. 
  725.             //
  726.                str mystr("Some demo text", 100, 200);
  727.             
  728.             //
  729.             // Define (mystr2) to contain substr formed from four characters 
  730.             // of (mystr1) starting at position 1. 
  731.             // mystr2 will contain "trin" 
  732.             //
  733.                str mystr1("string 1");
  734.                str mystr2(mystr1(1,4)); // "trin" 
  735.             
  736.             //
  737.             // Define str AnotherStr containing mystr 
  738.             //
  739.                str AnotherStr(mystr);  
  740. MEMBER FUNCTION
  741. OPERATORS
  742.  
  743. const char *  operator const char * () const;   
  744.  
  745.             Return pointer to this str's character buffer.  Compiler will
  746.             automatically call this when a cast to a (const char*) is
  747.             necessary.  Instances of  str can be used interchangeably with
  748.             const  char *.
  749.  
  750.             
  751.  
  752.             For example, when using the ansi C str library.  
  753.             //
  754.             // find location of "234" in MyString 
  755.             //
  756.             // foundptr = "2345 012345"
  757.             //
  758.                str MyString("012345 012345"); 
  759.                char * foundptr = strstr(MyString, "234"); 
  760.             
  761.             
  762.             //
  763.             // However you will not be allowed to use str  
  764.             // interchangeably with (char *). 
  765.             //
  766.                str MyString("012345"); 
  767.                strcpy(MyString, "hello");  //compiler type-checking error. 
  768.             
  769.             
  770. ()          const char * operator()() const; 
  771.  
  772.             Return pointer to this str's character buffer.
  773.  
  774.             
  775.  
  776. (int)       operator()(int index) const; 
  777.  
  778.             Return pointer to this str's character buffer starting  at
  779.             position (index).
  780.  
  781.             
  782.             //
  783.             // find location of "234" in MyString starting at offset 5
  784.             //
  785.             // foundptr = "2345"
  786.             //
  787.                str MyString("012345 012345"); 
  788.                char * foundptr = strstr(MyString(5), "234"); 
  789.             
  790.             
  791.  
  792. (int,int)   substr operator()(int pos, int num); 
  793.  
  794.             Substr operations supported using (int,int) notation. This member
  795.             function has two uses.  It can be used to  extract a substring
  796.             from a given string by using it on the right-hand-side of an
  797.             expression.  It extracts (num) characters starting at offset (pos)
  798.             of the string.  For example the following code fragment
  799.             concatenates two substrings.
  800.  
  801.             
  802.              {  
  803.                str myString("abdefghijklmnopqrstuvwxyz");
  804.                cout << myString(0,3) + myString(23,3); // "abcxyz";  
  805.              }
  806.             This member function can also be used to assign a selected region
  807.             of a string when used on the left-hand-side of an expression.  It
  808.             replaces (num) characters starting at offset (pos) of the string
  809.             with the left-hand-side of an  expression.
  810.  
  811.             For example, the following code fragment replaces "test"  with
  812.             "survey" by using a substr operation.
  813.  
  814.             
  815.  
  816.              {
  817.                str test_substr1("This is a test");  
  818.                int pos = test_substr1.index("test");
  819.                if (pos>=0) test_substr1(pos, 4) = "survey"; 
  820.              }
  821.             
  822.  
  823.  
  824. []          operator char& operator[](int position);
  825.  
  826.             Return reference to character buffer at offset position.
  827.  
  828.             
  829.             Example []:
  830.             //
  831.             //  Can access str as an array of char for assignment purposes. 
  832.             //
  833.                str MyString("012345"); 
  834.                MyString[4]='0';        // MyString = "012305"
  835.             
  836.             
  837. []          operator char operator[](int position) const;
  838.  
  839.             Return character at offset position of character buffer. This
  840.             version is only called if the calling str object is a constant
  841.             object.  It is provided because it is significantly faster than
  842.             the non-const version of operator [].
  843.  
  844.             
  845.             Example []:
  846.             //
  847.             //  Can access str as an array of char for retrieval purposes.
  848.             //
  849.                const str MyString("012345"); 
  850.                cout << MyString[4];  // writes '4' to screen
  851.             
  852.             
  853. =           str & operator = (const str & s);     // s = str;
  854.             str & operator = (const substr & s);  // s = substr;
  855.             str & operator = (const char * s);    // s = charptr
  856.             str & operator = (const char s);      // s = character
  857.  
  858.             Assign (s) to this str.
  859.  
  860.  
  861.  
  862.             Example:
  863.             
  864.              {
  865.                str s,t;
  866.                t = 'a';    // t = "a"
  867.                t = "abc";  // t = "abc"
  868.                s = t;      // s = "abc"
  869.                s = t(1,2); // s = "bc"
  870.              };
  871.             
  872.             
  873. +=          str & operator += (const str & s);  // s += str
  874.             str & operator += (const char * s); // s += charptr
  875.             str & operator += (const char s); // s += char
  876.  
  877.             Concatenate (s) to this str
  878.  
  879.  
  880.  
  881.             Example:
  882.             
  883.              {
  884.                str s;
  885.                str t="123";
  886.                s += 'a';      // s = "a"
  887.                s += "abc";    // s = "aabc"
  888.                s += t;     // s = "aabc123"
  889.                s += t(1,2);   // s = "aabc12323"
  890.              };
  891.             
  892.  
  893. <<          str & operator << (const char * s); // s << charptr
  894.             str & operator << (const str& s); // s << str
  895.             str & operator << (const int s);  // s << int
  896.             str & operator << (const char s); // s << char
  897.  
  898.             Concatenate (s) to this str.  Operator "<<" is only provided
  899.             because it has a more natural associativity (left to right) than
  900.             operator "+=" when concatenating a series.
  901.  
  902.             
  903.             Examples:
  904.              {
  905.                str s;
  906.                str t="123";
  907.                int i=99;
  908.                s << 'a';      // s = "a"
  909.                s << "abc"; // s = "aabc"
  910.                s << t;     // s = "aabc123"
  911.                s << i;     // s = "aabc12399"
  912.                s << t(1,2);   // s = "abbc1239923"     
  913.              };
  914.             
  915.              {
  916.                str testconcat1(" there in ");
  917.                int year = 1992;
  918.                str test;
  919.                test << "hello" << testconcat1 
  920.                   << year << '.';      // test = hello there in 1992.
  921.              }
  922.             
  923.             
  924. +           str operator+(const str &) const;
  925.             str operator+(const substr &) const;
  926.             str operator+(const char * b) const;
  927.             str operator+(const char b) const;
  928.             friend str operator+(const char *, const str &); 
  929.  
  930.             Concatenate s1 and s2 and return the result.  
  931.  
  932.             
  933.             {
  934.                str a("123");
  935.                str s = a + "abc";      // s = "123abc"
  936.             }
  937.             
  938.             Notes on efficiency:  For optimal perfomance, avoid cascading
  939.             operator "+" since temporary objects will be created.  Use
  940.             operators "+=",  "<<" , or the stream() member function.  Operator
  941.             "+=" and "<<" are more efficient than stream(), since stream()
  942.             must create an instance of dynstream the first time it is used,
  943.             but they are not as flexible or convenient.  
  944.  
  945.             
  946.  
  947. FRIEND/GLOBAL
  948. FUNCTION OPERATORS
  949.             
  950.  
  951. ==,!=,<=    int operator==(const str & s1, const str & s2)
  952. >=,<,>      Equal to, not equal to, less than, etc. relational operators
  953.             supported.  Comparison of s1 and s2 is determined by the case
  954.             sensitivity of s1.
  955.  
  956.  
  957.             Example for relational operators:
  958.             //
  959.             // The following code fragment will yield an output of 
  960.             // "010101", signifying false, true, false, true, false, true.
  961.             //
  962.                str a("abc");
  963.                str b("def");
  964.                cout << (a == b);
  965.                cout << (a != b);
  966.                cout << (a >= b);
  967.                cout << (a <= b);
  968.                cout << (a > b);
  969.                cout << (a < b);
  970.  
  971. MEMBER
  972. FUNCTIONS
  973.  
  974. assign      str & assign (const char * source, int len)
  975.  
  976.             Assign (len) characters from (source) to this str.
  977.  
  978.             Example:
  979.  
  980.             
  981.                str a;
  982.                str b="0123456789";
  983.                a.assign(b(5), 5);   // a = "56789";
  984.             
  985.  
  986. caseSensitive int caseSensitive(void) const;
  987.  
  988.             Returns the case sensitivity for the current str object.
  989.  
  990.             
  991.  
  992. index       int index(const char * s, int start=0) const;
  993.  
  994.             Search this str for character string (s) and return the offset
  995.             where a match occurs.  Search starts at offset (start).   Return
  996.             -1 if no match is found.  Case sensitivity is determined by this
  997.             str instance.  Case is sensitive by default when the str is
  998.             created, but can be overridden through member  function
  999.             setCaseSensitive(int).
  1000.  
  1001.             
  1002.  
  1003. index       int index(const regX& reg, int start=0) const;
  1004.  
  1005.             Search this str for regular expression (reg) and return the offset
  1006.             where a match occurs.  Search starts at offset (start).   Return
  1007.             -1 if no match is found.  
  1008.  
  1009.             
  1010.             //
  1011.             // Search for the first floating point number
  1012.             //
  1013.             //    pos = 20
  1014.             //
  1015.             
  1016.              {
  1017.                regX floatingPointNumber ("[0-9]+[.][0-9]+");
  1018.                str a = "pi is approximately 3.14159265";
  1019.                int pos = a.index(floatingPointNumber);
  1020.              }
  1021.             
  1022. index       int index(const regX& reg, int * matchLen, int start=0) const;
  1023.  
  1024.             Same as index(const regular&, int) but returns the length of the
  1025.             matched string in *matchLen.
  1026.  
  1027.             
  1028.             //
  1029.             // Search for the first floating point number
  1030.             //
  1031.             //    pos = 20
  1032.             //    matchlen = 10
  1033.             //
  1034.             
  1035.              {
  1036.                regX floatingPointNumber ("[0-9]+[.][0-9]+");
  1037.                str a = "pi is approximately 3.14159265";
  1038.                int matchlen;
  1039.                int pos = a.index(floatingPointNumber, &matchlen);
  1040.              }
  1041.             
  1042.             
  1043. insert      int insert(int pos, char ch);
  1044.  
  1045.             Insert char (ch) starting at offset (pos) of this str.  Insertion
  1046.             can fail if the str is already full, and the str is not allowed to
  1047.             expand (constructed with memincr=0).
  1048.  
  1049.             
  1050.              {
  1051.                a = "abcdefghi";
  1052.                a.insert(5, '1');    // a = "abcde1fghi"
  1053.              }
  1054.  
  1055.  
  1056. insert      int insert(int pos, const char * insertStr); 
  1057.  
  1058.             Insert character buffer insertStr starting at offset (pos) of this
  1059.             str.  Insertion can fail if the insertStr would cause this str to
  1060.             overflow, and the str is not allowed to expand (constructed with
  1061.             memincr=0).
  1062.  
  1063.             
  1064.              {
  1065.                a = "abcdefghi";
  1066.                a.insert(5, "12");    // a = "abcde12fghi"
  1067.              }
  1068.             
  1069.             
  1070. length      int length(void) const;  
  1071.  
  1072.             Return current string length of buffer.
  1073.  
  1074.             
  1075.              {
  1076.                str MyString("abc");
  1077.                cout << MyString.length();   // writes 3 to screen.
  1078.              }
  1079.             
  1080.             
  1081. pad         str& pad(int padsize, int t=right, char padchar = ' ');
  1082.  
  1083.             Pad (padchar) characters to the right and/or left of this str
  1084.             yielding a string of length (padsize).   The original string is
  1085.             modified.  The padtype can be one of (right, left, or both).  
  1086.  
  1087.             
  1088.             
  1089.             //
  1090.             // This code performs the following.
  1091.             //
  1092.             //    a = "hello there                     "
  1093.             //    a = "*********************hello there"
  1094.             //    a = "          hello there           "
  1095.             //
  1096.             //
  1097.             
  1098.                str a("hello there");
  1099.                a.pad(32);
  1100.             
  1101.                a = "hello there";
  1102.                a.pad(32, str::left,'*');
  1103.             
  1104.                a = "hello there";
  1105.                a.pad(32, str::both);
  1106.             
  1107.             
  1108. remove      void remove(int pos, int numdel=1); 
  1109.  
  1110.             Remove (numdel) characters starting at position (pos) of this str.
  1111.  
  1112.             
  1113.              {
  1114.                a = "abcdefghi";
  1115.                a.remove(5, 2);   // a = "abcdehi"
  1116.              }
  1117.  
  1118.  
  1119. replace     int replace(const regX& reg, const char * replaceStr, int
  1120.             start=0, int numReplacements=1);
  1121.  
  1122.             Replace occurrences of the pattern (reg) with (replaceStr).
  1123.             Replacement begins at offset (start) of this string, and at most
  1124.             (numReplacements) replacements are performed.  The number of
  1125.             actual replacements is returned.
  1126.  
  1127.             
  1128.             //
  1129.             // Replace first occurance of whitespace with a single blank
  1130.             //
  1131.             // a = "A great   string class"
  1132.             //
  1133.              regX whiteSpace("[\t ]+");
  1134.              str a = "A  \t  great   string class";
  1135.              a.replace(whiteSpace," ");
  1136.             
  1137.             
  1138. replace     int replace(const regX& reg, const char * replaceStr,       int*
  1139.             startPtr, int numReplacements=1);
  1140.  
  1141.             Replace occurrences of the regular expression (reg) with
  1142.             (replaceStr).  Replacement begins at offset (*startPtr) of this
  1143.             string, and at most (numReplacements) replacements are performed.
  1144.             The number of actual replacements is returned.  (*startPtr) is
  1145.             updated to begin after the matched pattern or set to -1 if no
  1146.             match found.
  1147.  
  1148.             
  1149.             //
  1150.             // Replace all whitespace with a single blank.
  1151.             //
  1152.             // a = "A great string class"
  1153.             //
  1154.                regX whiteSpace("[\t ]+");
  1155.                str a = "A    great    string  \t class";
  1156.             
  1157.                int pos=0;
  1158.                while (a.replace(whiteSpace, " ", &pos));
  1159.             
  1160.             
  1161. replace     int replace(const char * pattern, const char * replaceStr,
  1162.             int start=0, int numReplacements=1);
  1163.  
  1164.             Replace occurrences of the character string (pattern) with
  1165.             (replaceStr).  Replacement begins at offset (start) of this
  1166.             string, and at most (numReplacements) replacements are performed.
  1167.             The number of actual replacements is returned.
  1168.  
  1169.             
  1170.             //
  1171.             // Replace 2 occurrences of "/" with " " starting at pos 3
  1172.             //
  1173.             // a = "A/great string class"
  1174.             //
  1175.                str a = "A/great/string/class";
  1176.                int pos=0;
  1177.                a.replace("/", " ", 3, 2);
  1178.             
  1179.             
  1180. replace     int replace(const char * pattern, const char * replaceStr,
  1181.             int * startPtr, int numReplacements=1);
  1182.  
  1183.             Replace occurrences of the character string (pattern) with
  1184.             (replaceStr).  Replacement begins at offset (start) of this
  1185.             string, and at most (numReplacements) replacements are performed.
  1186.             The number of actual replacements is returned.   (*startPtr) is
  1187.             updated to begin after the matched pattern or set to -1 if no
  1188.             match found.
  1189.  
  1190.             
  1191.             //
  1192.             // Replace all occurrences of "/" with " "
  1193.             //
  1194.             // a = "A great string class"
  1195.             //
  1196.                a = "A/great/string/class";
  1197.                int pos=0;
  1198.                while (a.replace("/", " ", &pos));
  1199.             
  1200.             
  1201. replaceAll  int replaceAll(const char * pattern, const char * replaceStr,
  1202.                   int pos=0);
  1203.  
  1204.             Replace all occurrences of the character string (pattern) with
  1205.             (replaceStr).  Replacement begins at offset (start) of this
  1206.             string.   The number of actual replacements is returned.
  1207.  
  1208.             
  1209.             //
  1210.             // Replace all occurrences of "!" with " "
  1211.             //
  1212.             // a = "A great string class"
  1213.             //
  1214.                str a = "A!great!string!class";
  1215.                a.replaceAll("!", " ");
  1216.             
  1217.             
  1218. replaceAll  int replaceAll(const regX& reg, const char * replaceStr,
  1219.             int pos=0);
  1220.  
  1221.             Replace all occurrences of the regular expression (erg) with
  1222.             (replaceStr).  Replacement begins at offset (start) of this
  1223.             string.   The number of actual replacements is returned.
  1224.  
  1225.             
  1226.             //
  1227.             // Replace all whitespace with a single blank
  1228.             //
  1229.                regX whiteSpace("[\t ]+");
  1230.                str a = "A    great    string  \t class";
  1231.                a.replaceAll(whiteSpace," "); // a = "A great string class"
  1232.  
  1233.  
  1234. search      int search(const char * pattern, int *startPtr) const;
  1235.  
  1236.             Search for the character string (pattern) and return 1 if
  1237.             (pattern) is found.  Searching begins at offset (*startPtr) of
  1238.             this string.  (*startPtr) is updated to the starting position of
  1239.             the match or set to -1 if no match is found.
  1240.  
  1241.             
  1242.              {
  1243.                str a = "I love snow. God is love.";
  1244.                str love = "love";
  1245.                int pos = 0;
  1246.                if (a.search(love, &pos))     // pos = 2
  1247.                   cout << "there is love";   // "there is love"
  1248.                pos+= love.length();
  1249.                if (a.search(love, &pos))     // pos = 20
  1250.                   cout << "there is more love"; // "there is more love"
  1251.              }
  1252.             
  1253.             
  1254. search      int search(const char * pattern, int start=0) const;
  1255.  
  1256.             Search for the character string (pattern) and return 1 if
  1257.             (pattern) is found.  Searching begins at offset (start) of this
  1258.             string.  
  1259.  
  1260.             
  1261.              {
  1262.                str a = "I love snow";
  1263.                if (a.search("love"))
  1264.                   cout << "there is love";   // "there is love"
  1265.              }
  1266.  
  1267.  
  1268. search      int search(const regX& reg, int *startPtr) const;
  1269.  
  1270.             Search for the regular expression reg in this string and return 1
  1271.             if (reg) is found.  Searching begins at offset (*startPtr) of this
  1272.             string.  (*startPtr) is updated to the starting position of the
  1273.             match, or -1 if no match is found.  
  1274.  
  1275.             
  1276.              {
  1277.                regX number("[0-9]+");
  1278.                str a = "John 3:16";
  1279.                int pos=0;
  1280.                a.search(number, &pos);   // pos = 5;
  1281.              }
  1282.             
  1283.             
  1284. search      int search(const regX& reg, int start=0) const;
  1285.  
  1286.             Search for the regular expression reg in this string and return 1
  1287.             if (reg) is found.  Searching begins at offset (start) of this
  1288.             string.  
  1289.  
  1290.             
  1291.  
  1292.              {
  1293.                regX number("[0-9]+");
  1294.                a = "John 3:16";
  1295.                if (a.search(number))
  1296.                   cout << "found number";  // "found number"
  1297.              }
  1298.  
  1299.  
  1300. search      int search (const regX&, str * matchPtr=0, int start=0) const;
  1301.  
  1302.             Search for the regular expression reg in this string and return 1
  1303.             if (reg) is found. Searching begins at offset (start) of this
  1304.             string.  The matched pattern is saved as (*matchPtr).
  1305.  
  1306.             
  1307.              {
  1308.                regX number("[0-9]+");
  1309.                str a = "Bobby Fisher: world champion in 1993?"
  1310.                str match;
  1311.                a.search(number, &match);  // match = "1993"
  1312.              }
  1313.             
  1314.             
  1315. search      int search(const regX& reg, str* matchPtr,      int* startPtr)
  1316.             const;
  1317.  
  1318.             Search for the regular expression reg in this string and return
  1319.             0/1 if (reg) is found/not found.  Searching begins at offset
  1320.             (*startPtr) of this string.  (*startPtr) is updated to the
  1321.             starting position of the match, or -1 if not match is found.  The
  1322.             matched pattern is saved as (*matchPtr).
  1323.  
  1324.             
  1325.              {
  1326.                regX number("[0-9]+");
  1327.                str month, day, year;
  1328.                str a = "My wife's birthday is 4/12/1968.";
  1329.                int pos=0;
  1330.                a.search(number, &month, &pos);   // month = "4";
  1331.                pos+= month.length();
  1332.                a.search(number, &day, &pos);    // day = "12";
  1333.                pos+= day.length();
  1334.                a.search(number, &year, &pos);      // year = "1968";
  1335.              }
  1336.  
  1337. size        int size(void) const;    
  1338.  
  1339.             Return current size of memory allocated for buffer.
  1340.  
  1341.             
  1342.              {
  1343.                str MyString("abc", 80);
  1344.                cout << MyString.size();   // writes 80 to screen.
  1345.              }
  1346.             
  1347.             
  1348. setCaseSensitive  void setCaseSensitive(int val);
  1349.  
  1350.             Set the case sensitivity for the current str object.  If (val) is
  1351.             0 then string comparisons and searches will not be case sensitive.
  1352.             If (val) is 1 then they will be case sensitive.
  1353.  
  1354.             
  1355.  
  1356. stream      ostream& stream(void);
  1357.  
  1358.             Return ostream for this str.  Consult your iostream documentation
  1359.             for details on using an ostream.
  1360.  
  1361.             
  1362.             Examples stream():
  1363.             //
  1364.             // getTimeStr() converts a time specification into a string of 
  1365.             // the format "hh:mm:ss" using leading zeros.
  1366.             //
  1367.                str getTimeStr(int hour, int minute, int second)
  1368.                {
  1369.                   str timestr;
  1370.                   timestr.stream() << setfill('0') << setw(2) << hour
  1371.                      << ":" << setfill('0') << setw(2) << minute
  1372.                      << ":" << setfill('0') << setw(2) << second;
  1373.                   return timestr;  
  1374.                };
  1375.             
  1376.             //
  1377.             // Use stream operation to concatenate two strings.
  1378.             //
  1379.                str a;
  1380.                a.stream() << "Hello there."; // a = "Hello there"
  1381.                a.stream() << " Goodbye." // a = "Hello there. Goodbye."
  1382.             
  1383.                
  1384. stream      ostream& stream(int p);
  1385.  
  1386.             Return ostream for this str and move the ostream put pointer to
  1387.             offset (p).  Same functionality as stream(void) except that the
  1388.             user can change the stream put pointer.
  1389.  
  1390.             
  1391.  
  1392.             Example stream(int):
  1393.             
  1394.                str a;
  1395.                a.stream()  << "Hello there.";   // a = "Hello there."
  1396.                a.stream(0) << "Hello again.";   // a = "Hello again."
  1397.             
  1398.             
  1399. strip       str& strip(int striptype=trailing, const char * stripchars= "
  1400.             \t");
  1401.  
  1402.             Strip leading and/or trailing characters from the str and return
  1403.             the resulting str.  The original string is modified.  The strip
  1404.             type (striptype) can be one of (leading, trailing, or both).
  1405.             (stripchars) is a character string that contains a set of
  1406.             characters to strip.  The default is to strip trailing spaces and
  1407.             tabs.
  1408.  
  1409.             
  1410.             Example strip:
  1411.             
  1412.                str origstr("********hello there        ");
  1413.                str a = origstr;  
  1414.                a.strip();        // a = "********hello there        "
  1415.             
  1416.                a = origstr;
  1417.                a.strip(str::leading,"*"); // a = "hello there        "
  1418.             
  1419.                a = origstr;
  1420.                a.strip(str::both," *");   // a = "hello there"
  1421.             
  1422.  
  1423.             
  1424. strip       str& strip(int striptype=trailing, char stripchar);
  1425.  
  1426.             Strip leading and/or trailing characters (as defined by stripchar)
  1427.             from the str and return the resulting str.  The original string is
  1428.             modified.  The strip type (striptype) can be one of (leading,
  1429.             trailing, or both).
  1430.  
  1431.             
  1432.             //
  1433.             // This code performs the following.
  1434.             //
  1435.             //    a = "********hello there"
  1436.             //    a = "hello there"
  1437.             //
  1438.                str a("********hello there        ");
  1439.                a.strip(str::trailing,' ');
  1440.                a.strip(str::leading,'*');
  1441.  
  1442.  
  1443.  
  1444. FRIEND/GLOBAL
  1445. FUNCTIONS
  1446.  
  1447.  
  1448. >>          friend istream& operator >> (istream&, str &);
  1449.  
  1450.             Overload istream input operator to support str objects.
  1451.  
  1452.             
  1453.                str a;
  1454.                cin >> a;     // read string from keyboard and store in a
  1455.             
  1456.             
  1457. <<          friend ostream& operator << (ostream&, const str &);
  1458.  
  1459.             Overload ostream input operator to support str objects.
  1460.  
  1461.             
  1462.  
  1463.                str a("hello there");
  1464.                cout << a << endl;   // write string to screen
  1465.             
  1466.             
  1467. lowercase   str lowercase(const char *);
  1468.  
  1469.             Return lower case of character buffer
  1470.  
  1471.             
  1472.              {
  1473.                str a("Abc");
  1474.                cout << lowercase(a);      // outputs "abc"
  1475.              }
  1476.             
  1477.             
  1478. pad         str pad(const char * s, int padsize, 
  1479.                     int t=str::right, char padchar = '
  1480.             ');
  1481.  
  1482.             Pad (padchar) characters to the right and/or left of s, yielding a
  1483.             string of length (padsize).    The padtype can be one of (right,
  1484.             left, or both).  
  1485.  
  1486.             
  1487.             //
  1488.             // This code performs the following.
  1489.             //
  1490.             // a = "hello there                     "
  1491.             // a = "*********************hello there"
  1492.             // a = "          hello there           "
  1493.             //
  1494.                str origstr("hello there");
  1495.                str a = pad(origstr, 32);
  1496.                a = pad(origstr, 32, str::left,'*');
  1497.                a = pad(origstr, 32, str::both);
  1498.             
  1499.             
  1500. strip       str strip(const char * s, int striptype=str::trailing, 
  1501.                       const char * stripchar);
  1502.  
  1503.             Strip leading and/or trailing characters from (s) and return the
  1504.             resulting str.  The strip type (striptype) can be one of (leading,
  1505.             trailing, or both).  (stripchars) is a character string that
  1506.             contains a set of characters to strip.  The default is to strip
  1507.             trailing spaces and tabs.
  1508.  
  1509.             
  1510.             Example strip:
  1511.             
  1512.             //
  1513.             // This code performs the following.
  1514.             //
  1515.             //    a = "********hello there        "
  1516.             //    a = "hello there        "
  1517.             //    a = "hello there"
  1518.             //
  1519.                str origstr("********hello there        ");
  1520.                str a = strip(origstr);
  1521.                a = strip(origstr, str::leading,"*");
  1522.                a = strip(origstr, str::both," *");
  1523.             
  1524.  
  1525. strip       str strip(const char * s, int striptype=trailing, char stripchar);
  1526.  
  1527.             Strip leading and/or trailing characters (as defined by stripchar)
  1528.             from s and return the resulting str.   The strip type (striptype)
  1529.             can be one of (leading, trailing, or both).
  1530.  
  1531.             //
  1532.             // This code performs the following.
  1533.             //
  1534.             //    a = "********hello there"
  1535.             //    a = "hello there        "
  1536.             //
  1537.                str origstr("********hello there        ");
  1538.                str a = strip(origstr, str::trailing,' ');
  1539.                a = strip(origstr, str::leading,'*');
  1540.             
  1541.             
  1542. uppercase   str uppercase(const char *); 
  1543.  
  1544.             Return upper case of character buffer
  1545.  
  1546.             
  1547.              {
  1548.                str a("Abc");
  1549.                cout << uppercase(a);   // outputs "ABC"
  1550.              }
  1551.             
  1552.  
  1553.  
  1554.   PROTECTED
  1555. STATIC MEMBER
  1556.   FUNCTIONS
  1557.  
  1558. setDefaultCaseSensitive   
  1559.             void setDefaultCaseSensitive(int val);
  1560.  
  1561.             Set the default case sensitivity to val.  The default is used when
  1562.             creating new instances of str.
  1563.  
  1564.  
  1565. regX CLASS REFERENCE
  1566. constructor   regX(void); 
  1567.  
  1568.             Default constructor a regular expression.   User should assign
  1569.             regular expression using operator =  before using it.
  1570.  
  1571.  
  1572. constructor   regX(const char * regexp); 
  1573.  
  1574.             Create a regular expression defined by the pattern (regexp).   
  1575.             The regular expression is automatically compiled.
  1576.  
  1577.             
  1578.  
  1579. constructor   regX(const regX& regexp); 
  1580.  
  1581.             Copy constructor for regular expressions.
  1582.  
  1583.             
  1584.  
  1585. =           regX& operator=(const char * regexp);
  1586.  
  1587.             Use the regular expression defined by regexp.   The regular
  1588.             expression is automatically compiled.
  1589.  
  1590.             
  1591.  
  1592. =           regX& operator=(const regX& regexp);
  1593.  
  1594.             Use the regular expression defined by regexp.   
  1595.  
  1596.             
  1597.  
  1598. error       int error(void) const;
  1599.  
  1600.             Return 1 if there was an error in compiling the regular
  1601.             expression.
  1602.  
  1603.  
  1604.  
  1605. index       int index(const char * searchStr, int * matchLenPtr,  
  1606.                       int start=0, int caseSensitive=1);
  1607.  
  1608.             Search for this regular expression in the character buffer
  1609.             searchStr starting at position start.  If the match is found save
  1610.             the length of the match in *matchLenPtr.  Case sensitivity is
  1611.             determined by caseSensitive).   Return position where match is
  1612.             found or -1 if no match is found.
  1613.  
  1614.  
  1615.  
  1616.  
  1617.  
  1618.          ----------------end-of-author's-documentation---------------
  1619.  
  1620.                          Software Library Information:
  1621.  
  1622.                     This disk copy provided as a service of
  1623.  
  1624.                            Public (software) Library
  1625.  
  1626.          We are not the authors of this program, nor are we associated
  1627.          with the author in any way other than as a distributor of the
  1628.          program in accordance with the author's terms of distribution.
  1629.  
  1630.          Please direct shareware payments and specific questions about
  1631.          this program to the author of the program, whose name appears
  1632.          elsewhere in  this documentation. If you have trouble getting
  1633.          in touch with the author,  we will do whatever we can to help
  1634.          you with your questions. All programs have been tested and do
  1635.          run.  To report problems,  please use the form that is in the
  1636.          file PROBLEM.DOC on many of our disks or in other written for-
  1637.          mat with screen printouts, if possible.  PsL cannot debug pro-
  1638.          programs over the telephone, though we can answer questions.
  1639.  
  1640.          Disks in the PsL are updated  monthly,  so if you did not get
  1641.          this disk directly from the PsL, you should be aware that the
  1642.          files in this set may no longer be the current versions. Also,
  1643.          if you got this disk from another vendor and are having prob-
  1644.          lems,  be aware that  some files may have become corrupted or
  1645.          lost by that vendor. Get a current, working disk from PsL.
  1646.  
  1647.          For a copy of the latest monthly software library newsletter
  1648.          and a list of the 4,000+ disks in the library, call or write
  1649.  
  1650.                            Public (software) Library
  1651.                                  P.O.Box 35705
  1652.                             Houston, TX 77235-5705
  1653.  
  1654.                                  Orders only:
  1655.                                 1-800-2424-PSL
  1656.                               MC/Visa/AmEx/Discover
  1657.  
  1658.                           Outside of U.S. or in Texas
  1659.                           or for general information,
  1660.                               Call 1-713-524-6394                 
  1661.